﻿using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ES
{
  public   class ElasticSearchBase
    {
        private static readonly Lazy<ElasticSearchBase> lazy = new Lazy<ElasticSearchBase>(() => new ElasticSearchBase());
        private IElasticClient EsClient;
        public ElasticSearchBase()
        {
            EsClient = ElasticSearchConfig.EsClient;
        }
        public static ElasticSearchBase Instance
        {
            get
            {
                return lazy.Value;
            }
        }

        /// <summary>
        /// 创建索引 
        /// </summary>
        /// <returns></returns>
        public bool CreateIndex<T>() where T : class
        {
            //EsClient.IndexMany<PolicyInfo>(policyInfos, "policyInfos");
            //CreateIndex 创建索引，mapping  映射 
            var indexName = typeof(T).Name.ToLower();
            var response = EsClient.CreateIndex(indexName, seting => seting
             .Settings(setting => setting.NumberOfShards(5).NumberOfReplicas(1))//指定了该索引的分片数为5、副本数为1
              .Mappings(m => m.Map<T>(map => map.AutoMap())));//映射创建type
            return response.Acknowledged;
        }

        /// <summary>
        /// 删除索引
        /// </summary>
        /// <returns></returns>
        public bool DeleteIndex<T>() where T : class
        {
            //删除指定索引所在节点下的所有索引 
            var indexName = typeof(T).Name.ToLower();
            var descriptor = new DeleteIndexDescriptor(indexName);
            var result = EsClient.DeleteIndex(descriptor);
            return result.IsValid;
        }

        /// <summary>
        /// 批量添加文档
        /// </summary>
        /// <returns></returns>
        public bool AddDocumentBulk<T>(List<T> list) where T : class
        {
            var indexName = typeof(T).Name.ToLower();
            var result = EsClient.IndexMany<T>(list, indexName);//批量增加文档   policyinfos 索引必须为小写
            return result.IsValid;
        }

        /// <summary>
        /// 添加文档
        /// </summary>
        /// <returns></returns>
        public bool AddDocument<T>(T data) where T : class
        {
            var indexName = typeof(T).Name.ToLower();
            var result = EsClient.Index<T>(data, d => d.Index(indexName));//批量增加文档   policyinfos 索引必须为小写
            return result.IsValid;
        }

        /// <summary>
        /// 更新文档(根据ID 将指定的数据进行更新)
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="id">PID</param>
        /// <param name="data">指定修改的数据 格式为 new { Title = "12333" }</param>
        /// <returns></returns>
        public bool UpdateDocument<T>(long id, object data) where T : class
        {
            ///3 指定更新
           var indexName = typeof(T).Name.ToLower();
            var result = EsClient.Update<T, object>(id, upt => upt.Doc(data).Index(indexName));
            return result.IsValid;
        }

        /// <summary>
        /// 更新文档(根据ID 更新所有字段)
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="id">PID</param>
        /// <param name="data">指定修改的数据 格式为 new { Title = "12333" }</param>
        /// <returns></returns>
        public bool UpdateDocument<T>(long id, T data) where T : class
        {
            var indexName = typeof(T).Name.ToLower();
            DocumentPath<T> deletePath = new DocumentPath<T>(id).Index(indexName);
            var result = EsClient.Update(deletePath, (p) => p.Doc(data));
            return result.IsValid;
        }

        /// <summary>
        ///批量更新(根据ID集合修改指定字段)
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="ids">ID集合 格式为List<long></param>
        /// <param name="data">指定修改的数据 格式为 new { Title = "12333" }</param>
        /// <returns></returns>
        public bool UpdateDocumentBulk<T>(List<long> ids, object data) where T : class
        {
            var indexName = typeof(T).Name.ToLower();
            //var ids = new List<int>() { 4, 5 };
            var bulkQuest = new BulkRequest(indexName) { Operations = new List<IBulkOperation>() };
            foreach (var v in ids)
            {
                var operation = new BulkUpdateOperation<T, object>(v);
                operation.Doc = data;
                bulkQuest.Operations.Add(operation);
            }
            var result = EsClient.Bulk(bulkQuest);
            return result.IsValid;
        }


        /// <summary>
        /// 删除文档（根据ID删除）
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="id">id </param>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool DeleteDocument<T>(long id) where T : class
        {
            try
            {
                var indexName = typeof(T).Name.ToLower();
                DocumentPath<T> deletePath = new DocumentPath<T>(id).Index(indexName);
                var result = EsClient.Delete(deletePath);
                return result.IsValid;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// 批量删除(根据ID集合删除)
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="ids">ID List<long></param>
        /// <returns></returns>
        public bool DeleteDocumentBulk<T>(List<long> ids) where T : class
        {
            var indexName = typeof(T).Name.ToLower();
            // var ids = new List<int>() { 2, 3 };
            var bulkQuest = new BulkRequest(indexName) { Operations = new List<IBulkOperation>() };
            foreach (var v in ids)
            {
                bulkQuest.Operations.Add(new BulkDeleteOperation<T>(v));
            }
            var result = EsClient.Bulk(bulkQuest);
            return result.IsValid;
        }

        /// <summary>
        /// 查询所有（返回1000条数据）
        /// </summary>
        /// <returns></returns>
        public List<T> GetAll<T>() where T : class
        {
            var indexName = typeof(T).Name.ToLower();
            var searchResults = EsClient.Search<T>(s => s.Index(indexName).Sort(x => x.Field("PID", Nest.SortOrder.Descending)).From(0).Size(1000));
            return searchResults.Documents.ToList();
        }

        /// <summary>
        /// 查询索引数据
        /// </summary>
        /// <param name="doctorId"></param>
        /// <returns></returns>
        public List<T> Query<T>(string key) where T : class
        {
            var indexName = typeof(T).Name.ToLower();
            SearchDescriptor<T> searchDescriptor = new SearchDescriptor<T>().Index(indexName);

             //searchDescriptor.Query(q => q.QueryString(qs => qs.Query(key).DefaultOperator(Operator.And)));
            //searchDescriptor.Query(q => q.MatchPhrase(m => m.Field("PolicyKey").Query(key))).From(0).Size(90);
            // searchDescriptor.PostFilter(x => x.QueryString(t => t.Fields(f => f.Field("PolicyTitle")).Query(key)));
            searchDescriptor.Query(x => x.QueryString(t => t.Fields(f => f.Field("PolicyTitle")).Query(key))).From(0).Size(80);
            // searchDescriptor.Query(q => q.Match(m => m.Field("PolicyKey").Query(key))).From(0).Size(80);

            //TODO
            //分词搜索代码 待补充

            //排序  根据得分排序 
            searchDescriptor.Sort(x => x.Field("_score", Nest.SortOrder.Descending));
            var result = EsClient.Search<T>(searchDescriptor);
            return result.Documents.ToList();
        }
    }
}
